﻿using BCCommon;
using BCEntity.Sim.Admin.AdminPermissionConfig;
using Dapper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;

namespace BCData.Sim.Admin.AdminPermissionConfig
{
    public class AdminPermissionConfigData : IAdminPermissionConfigData
    {
        private readonly IDatabaseContext databaseContext;
        private const string QUERY = @"SELECT AdminPermissionConfigId,PermissionName,PermissionCode,PermissionLevel,PermissionPathCode FROM AdminPermissionConfig";

        public AdminPermissionConfigData(IDatabaseContext databaseContext)
        {
            this.databaseContext = databaseContext;
        }

        public async Task<AdminPermissionConfigEntity> Add(AdminPermissionConfigEntity entity)
        {
            string sql = SqlCommands.GetInsertSql("AdminPermissionConfig", new string[] { "PermissionName", "PermissionCode", "PermissionLevel", "PermissionPathCode" });
            sql = string.Format("{0} {1} WHERE AdminPermissionConfigId=LAST_INSERT_ID()", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PermissionName", entity.PermissionName.Trim(), DbType.AnsiString, size: 50);
            parameters.Add("?PermissionCode", entity.PermissionCode.Trim(), DbType.AnsiString, size: 150);
            parameters.Add("?PermissionLevel", entity.PermissionLevel, DbType.Int32, size: 10);
            parameters.Add("?PermissionPathCode", entity.PermissionPathCode.Trim(), DbType.String);
            return await this.databaseContext.Master.QueryFirstOrDefaultAsync<AdminPermissionConfigEntity>(sql, parameters, databaseContext.Transaction);
        }

        public async Task<bool> Update(AdminPermissionConfigEntity entity, List<int> adminPermissionMappingPageIds, List<long> adminPermissionRecordIds)
        {
            string sql = SqlCommands.GetUpdateSql("AdminPermissionConfig", new string[] { "PermissionName", "PermissionCode", "PermissionLevel", "PermissionPathCode" }, new string[] { "AdminPermissionConfigId" });
            string updateMappingSql = @"UPDATE AdminPermissionMappingPage SET PermissionCode=?PermissionCode WHERE FIND_IN_SET(AdminPermissionMappingPageId,?AdminPermissionMappingPageIds);";
            string updateRecordSql = @"UPDATE AdminPermissionRecord SET PermissionCode=?PermissionCode WHERE FIND_IN_SET(AdminPermissionRecordId,?AdminPermissionRecordIds);";

            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminPermissionConfigId", entity.AdminPermissionConfigId, DbType.Int64, size: 20);
            parameters.Add("?PermissionName", entity.PermissionName.Trim(), DbType.AnsiString, size: 50);
            parameters.Add("?PermissionCode", entity.PermissionCode.Trim(), DbType.AnsiString, size: 150);
            parameters.Add("?PermissionLevel", entity.PermissionLevel, DbType.Int32, size: 10);
            parameters.Add("?PermissionPathCode", entity.PermissionPathCode.Trim(), DbType.String);
            await this.databaseContext.Master.ExecuteAsync(sql, parameters, databaseContext.Transaction);

            DynamicParameters mappingParameters = new DynamicParameters();
            mappingParameters.Add("?PermissionCode", entity.PermissionCode.Trim(), DbType.AnsiString, size: 150);
            mappingParameters.Add("?AdminPermissionMappingPageIds", string.Join(',', adminPermissionMappingPageIds), DbType.AnsiString);
            await this.databaseContext.Master.ExecuteAsync(updateMappingSql, mappingParameters, databaseContext.Transaction);

            DynamicParameters recordParameters = new DynamicParameters();
            recordParameters.Add("?PermissionCode", entity.PermissionCode.Trim(), DbType.AnsiString, size: 150);
            recordParameters.Add("?AdminPermissionRecordIds", string.Join(',', adminPermissionRecordIds), DbType.AnsiString);

            return await this.databaseContext.Master.ExecuteAsync(updateRecordSql, recordParameters, databaseContext.Transaction) > 0;

        }

        public async Task<bool> CheckExists(long adminPermissionConfigId)
        {
            string sql = @"SELECT 1 FROM AdminPermissionConfig WHERE AdminPermissionConfigId=?AdminPermissionConfigId LIMIT 1";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminPermissionConfigId", adminPermissionConfigId, DbType.Int64, size: 20);
            return await this.databaseContext.Slave.ExecuteScalarAsync(sql, parameters) != null;
        }

        public async Task<bool> CheckExists(string permissionCode, string permissionPathCode = null)
        {
            List<string> wheres = new List<string>()
            {
                "PermissionCode=?PermissionCode"
            };
            DynamicParameters parameters = new DynamicParameters();

            parameters.Add("?PermissionCode", permissionCode.Trim(), DbType.AnsiString, size: 150);
            if (permissionPathCode.IsNotNull())
            {
                wheres.Add("PermissionPathCode=?PermissionPathCode");
                parameters.Add("?PermissionPathCode", permissionPathCode.Trim(), DbType.AnsiString);
            }
            string sql = string.Format("SELECT 1 FROM AdminPermissionConfig {0} LIMIT 1", wheres.Count > 0 ? " WHERE " + string.Join(" AND ", wheres) : "");
            return await this.databaseContext.Slave.ExecuteScalarAsync(sql, parameters) != null;
        }

        public void Delete(long adminPermissionConfigId)
        {
            string sql = @"DELETE FROM AdminPermissionConfig WHERE AdminPermissionConfigId=?AdminPermissionConfigId";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminPermissionConfigId", adminPermissionConfigId, DbType.Int64, size: 20);
            this.databaseContext.Master.Execute(sql, parameters, databaseContext.Transaction);
        }

        public async Task<IEnumerable<AdminPermissionConfigEntity>> GetList()
        {
            return await this.databaseContext.Slave.QueryAsync<AdminPermissionConfigEntity>(string.Format(" {0} ORDER BY PermissionPathCode ", QUERY));
        }

        public async Task<IEnumerable<AdminPermissionConfigEntity>> GetUnusedList()
        {
            string sql = @"SELECT * FROM (
	                        SELECT A.AdminPermissionConfigId,A.PermissionName,A.PermissionCode,A.PermissionLevel,A.PermissionPathCode,1 AS Disabled
	                        FROM AdminPermissionConfig A
	                        INNER JOIN AdminPermissionMappingPage B ON A.PermissionCode=B.PermissionCode
	                        UNION
	                        SELECT A.AdminPermissionConfigId,A.PermissionName,A.PermissionCode,A.PermissionLevel,A.PermissionPathCode,0 AS Disabled 
	                        FROM AdminPermissionConfig A
	                        LEFT OUTER JOIN AdminPermissionMappingPage B ON A.PermissionCode=B.PermissionCode
	                        WHERE B.AdminPermissionMappingPageId IS NULL
                        )T 
                        ORDER BY PermissionPathCode ASC";
            return await this.databaseContext.Slave.QueryAsync<AdminPermissionConfigEntity>(sql);
        }

        public async Task<(IEnumerable<AdminPermissionConfigEntity>, int)> Query(string permissionName, string permissionCode, string permissionPathCode, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            List<string> wheres = new List<string>();
            DynamicParameters parameters = new DynamicParameters();
            if (!string.IsNullOrWhiteSpace(permissionName))
            {
                wheres.Add("PermissionName LIKE  CONCAT('%',CONCAT(?PermissionName,'%'))");
                parameters.Add("?PermissionName", permissionName, DbType.AnsiString);
            }
            if (!string.IsNullOrWhiteSpace(permissionCode))
            {
                wheres.Add("PermissionPathCode LIKE  CONCAT('%',CONCAT(?PermissionCode,'%'))");
                parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString);
            }
            if (!string.IsNullOrWhiteSpace(permissionPathCode))
            {
                wheres.Add("PermissionPathCode LIKE CONCAT('%',CONCAT(?PermissionPathCode,'%'))");
                parameters.Add("?PermissionPathCode", permissionPathCode, DbType.AnsiString);
            }
            string sql = string.Format("{0} {1} ORDER BY {4} {5} LIMIT {2},{3};SELECT COUNT(1) FROM AdminPermissionConfig {1}",
                    QUERY,
                    wheres.Count > 0 ? " WHERE " + string.Join(" AND ", wheres) : "",
                    (pageIndex == 0 ? 0 : pageIndex - 1) * pageSize,
                    pageSize,
                    string.IsNullOrWhiteSpace(sortName) ? "AdminPermissionConfigId" : sortName,
                    ascending.HasValue && ascending.Value ? "ASC" : "DESC");

            return await this.databaseContext.Slave.QueryMultipleAsync<AdminPermissionConfigEntity, int>(sql, parameters);
        }

        public async Task<AdminPermissionConfigEntity> GetEntity(long adminPermissionConfigId)
        {
            string sql = string.Format(@"{0} WHERE AdminPermissionConfigId=?AdminPermissionConfigId LIMIT 1", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?AdminPermissionConfigId", adminPermissionConfigId, DbType.Int64, size: 20);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<AdminPermissionConfigEntity>(sql, parameters);
        }

        public async Task<AdminPermissionConfigEntity> GetEntity(string permissionCode)
        {
            string sql = string.Format(@"{0} WHERE PermissionCode=?PermissionCode LIMIT 1", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PermissionCode", permissionCode, DbType.AnsiString);
            return await this.databaseContext.Slave.QueryFirstOrDefaultAsync<AdminPermissionConfigEntity>(sql, parameters);
        }
    }
}
